package operatemodel

import (
	"errors"
	"server/global"
	"server/model"
	entry "server/model/entrance"
	"strconv"

	mapset "github.com/deckarep/golang-set/v2"

	"gorm.io/gorm"
)

func Getallarticle() (data []model.Article, code int) {
	d := model.DB.Find(&data)
	if d.RowsAffected == 0 || d.Error != nil {
		code = global.FAIL
		return
	}
	code = global.SUCCESS
	return
}

func Uploadarticle(data *entry.Uploadarticle) (code int) {
	//先检查分类是否存在
	d := model.DB.First(&model.Category{CategoryName: data.CategoryName})
	if d.RowsAffected == 0 || d.Error != nil {
		code = global.ERROR_FORMAT
		return
	}
	//添加数据
	d = model.DB.Create(&model.Article{
		Articlename:  data.Articletitle,
		Categoryname: data.CategoryName,
		Context:      data.Context,
		Describe:     data.Describe,
	})
	if d.RowsAffected == 0 || d.Error != nil {
		code = global.FAIL
		return
	}
	code = global.SUCCESS
	return
}

func Getonearticle(id int) (code int, data model.Article) {
	d := model.DB.Preload("Comments").Where("id=?", id).First(&data)
	if errors.Is(d.Error, gorm.ErrRecordNotFound) {
		code = global.REDIRECT
		return
	} else if d.Error != nil { //这个才是服务器错误
		code = global.FAIL
		return
	}
	code = global.SUCCESS
	return
}

func Deletearticle(id int) (code int) {
	d := model.DB.Delete(&model.Article{}, id)
	if d.RowsAffected == 0 || d.Error != nil {
		code = global.FAIL
		return
	}
	code = global.SUCCESS
	return
}

func Updatarticle(data *entry.Updatarticle) (code int) {
	//查询信息是否有效
	d := model.DB.Where("category_name=?", data.CategoryName).First(&model.Category{})
	if d.RowsAffected == 0 || d.Error != nil {
		code = global.FAIL
		return
	}
	var bin = new(model.Article)
	i, err := strconv.Atoi(data.ID) //model只能做主键查询
	if err != nil {
		code = global.ERROR_FORMAT
		return
	}
	bin.ID = uint(i)
	d = model.DB.Model(bin).Updates(model.Article{
		Categoryname: data.CategoryName,
		Context:      data.Context,
		Articlename:  data.Articletitle,
		Describe:     data.Describe,
	})
	if d.RowsAffected == 0 || d.Error != nil {
		code = global.FAIL
		return
	}
	code = global.SUCCESS
	return
}

//获取最新的8篇文章
func Fetchnewblog() (data []model.Article) {

	d := model.DB.Select("id", "created_at", "updated_at", "categoryname", "articlename").Order("created_at DESC").Limit(8).Find(&data)
	if d.RowsAffected == 0 || d.Error != nil {
		data = nil
	}
	return
}

//Flag:
func Getcategoryarticle(cate string, context bool) (data []model.Article, code int) {
	if context {

	} else {
		switch cate {
		case "go":
			d := model.DB.Select("ID", "describe", "Categoryname", "Articlename", "updated_at", "created_at").Order("created_at desc").Where("categoryname=?", "Golang").Find(&data)
			if errors.Is(d.Error, gorm.ErrRecordNotFound) {
				code = global.SUCCESS
				return
			} else if d.Error != nil {
				code = global.FAIL
				return
			}
		case "web":
			d := model.DB.Select("ID", "describe", "Categoryname", "Articlename", "updated_at", "created_at").Order("created_at desc").Where("categoryname=?", "前端").Find(&data)
			if errors.Is(d.Error, gorm.ErrRecordNotFound) {
				code = global.SUCCESS
				return
			} else if d.Error != nil {
				code = global.FAIL
				return
			}
		case "chat":
			d := model.DB.Select("ID", "describe", "Categoryname", "Articlename", "updated_at", "created_at").Order("created_at desc").Where("categoryname=?", "闲聊").Find(&data)
			if errors.Is(d.Error, gorm.ErrRecordNotFound) {
				code = global.SUCCESS
				return
			} else if d.Error != nil {
				code = global.FAIL
				return
			}
		default:
			//加载其他分类
			d := model.DB.Select("ID", "describe", "Categoryname", "Articlename", "updated_at", "created_at").Order("created_at desc").Not("categoryname=?", "golang").Not("categoryname=?", "前端").Not("categoryname=?", "闲聊").Find(&data)
			if errors.Is(d.Error, gorm.ErrRecordNotFound) {
				code = global.SUCCESS
				return
			} else if d.Error != nil {
				code = global.FAIL
				return
			}
		}
	}
	code = global.SUCCESS
	return
}

func Getcommentofarticle(id int, pagenum int) (comment []model.Comment, code int) {
	//先找找看有没有文章先
	d := model.DB.First(&model.Article{}, id)
	if errors.Is(d.Error, gorm.ErrRecordNotFound) {
		code = global.FAIL
		return
	} else if d.Error != nil {
		code = global.FAIL
		return
	}
	model.DB.Preload("User").Scopes(Padinate(pagenum, 10)).Where("Aid=?", id).Find(&comment)
	if errors.Is(d.Error, gorm.ErrRecordNotFound) {
		comment = nil
	} else if d.Error != nil {
		code = global.FAIL
		return
	}
	code = global.SUCCESS
	return
}

//Flag:添加评论
func Addcomment(Aid int, uname string, uemail string, comment string) (code int) {
	//查询文章是否存在
	d := model.DB.First(&model.Article{}, Aid)
	if d.RowsAffected == 0 || d.Error != nil {
		code = global.ERROR_FORMAT
		return
	}
	var com = model.Comment{
		Aid:          uint(Aid),
		CommentEmail: uemail,
		Context:      comment,
	}
	d = model.DB.Create(&com)
	if d.RowsAffected == 0 || d.Error != nil {
		code = global.FAIL
		return
	}
	code = global.SUCCESS
	return
}

func Getnumofcomment(id int) (num int64) {
	d := model.DB.First(&model.Article{})
	if errors.Is(d.Error, gorm.ErrRecordNotFound) {
		num = -1
		return
	} else if d.Error != nil {
		num = -1
		return
	}
	d = model.DB.Model(model.Comment{}).Where("Aid=?", id).Count(&num) //取操作,放最后
	if errors.Is(d.Error, gorm.ErrRecordNotFound) {
		num = 0
		return
	} else if d.Error != nil {
		num = -1
		return
	}
	return
}

//	mapset需要一个可比较的泛型接口,这样才可以做排序
func Searchblog(slice []string) (code int, modata []model.Article) {
	//使用set来存储数据 -->这样就不会重复了-->但是要求结构体中每个数值都是可比较的,有悖设计,下次再用->直接用map来实现
	var maper = make(map[string]model.Article)
	for _, v := range slice {
		var data []model.Article //循环获取数据
		//实现多字段模糊查询
		d := model.DB.Select("id", "created_at", "updated_at", "articlename", "describe").Where("CONCAT(`articlename`,`describe`)  LIKE ?  ", "%"+v+"%").Find(&data)
		if errors.Is(d.Error, gorm.ErrRecordNotFound) {
			continue
		} else if d.Error != nil {
			code = global.FAIL
			return
		} //重复key以最后一个为准-->合适
		for _, v1 := range data {
			maper[strconv.Itoa(int(v1.ID))] = v1
		}
	}
	for _, v := range maper {
		modata = append(modata, v)
	}
	code = global.SUCCESS
	return
}

func Gettimestamp() (code int, xin interface{}) {
	//获取从头到尾的数据整理好
	var data []model.Article //存储到set的时候就排序好了
	d := model.DB.Select("id", "created_at", "updated_at", "articlename", "categoryname").Find(&data)
	if errors.Is(d.Error, gorm.ErrRecordNotFound) {
		code = global.NOTFOUND
		return
	} else if d.Error != nil {
		code = global.FAIL
		return
	}
	//Note:map的多层嵌套要重复make声明-->否则会报nil错误
	var mapertime = make(map[string]map[string]map[string]model.Article)

	//Flag:第一次循环,找出存在的year ,month  存储在set里面[保证唯一性]
	var Year = mapset.NewSet[string]()
	var Month = mapset.NewSet[string]()
	for _, v := range data {
		var year = v.CreatedAt.Format("2006")
		var month = v.CreatedAt.Format("01")
		//map的添加只能全赋值,所以需要遍历:把一个月内的数据都赋值到这个月,再赋值给这个年,再遍历年
		Year.Add(year)
		Month.Add(month)
	}

	//Flag:遍历set ,以channel的方式实现
	for yeardata := range Year.Iter() { //遍历年
		//Flag:嵌套map在使用前要make创建空间
		mapertime[yeardata] = make(map[string]map[string]model.Article)
		var flag = true                     //Flag:用flag来进行多余数据处理
		for mondata := range Month.Iter() { //遍历月
			mapertime[yeardata][mondata] = make(map[string]model.Article)
			//Flag:核心代码实现:实现把这一年的这个月的数据存储好然后赋值到单一map中
			for _, v := range data {
				var year = v.CreatedAt.Format("2006")
				var month = v.CreatedAt.Format("01")
				var day = v.CreatedAt.Format("02")
				if year == yeardata && month == mondata {
					mapertime[yeardata][mondata][day] = v
					flag = false
				}
			}
			if flag {
				delete(mapertime[yeardata], mondata)
			}
			flag = true
		}
	}
	code = global.SUCCESS
	xin = mapertime
	return
}
